""" Common Intermediate Language (CIL).

This module contains supporting routines for CIL from the .NET framework.

See also:
https://en.wikipedia.org/wiki/List_of_CIL_instructions
"""

# Opcodes as found online:
opcodes = [
    (0x00, "nop"),
    (0x01, "break"),
    (0x02, "ldarg.0"),
    (0x03, "ldarg.1"),
    (0x04, "ldarg.2"),
    (0x05, "ldarg.3"),
    (0x06, "ldloc.0"),
    (0x07, "ldloc.1"),
    (0x08, "ldloc.2"),
    (0x09, "ldloc.3"),
    (0x0A, "stloc.0"),
    (0x0B, "stloc.1"),
    (0x0C, "stloc.2"),
    (0x0D, "stloc.3"),
    (0x0E, "ldarg.s"),
    (0x0F, "ldarga.s"),
    (0x10, "starg.s"),
    (0x11, "ldloc.s"),
    (0x12, "ldloca.s"),
    (0x13, "stloc.s"),
    (0x14, "ldnull"),
    (0x15, "ldc.i4.m1"),
    (0x16, "ldc.i4.0"),
    (0x17, "ldc.i4.1"),
    (0x18, "ldc.i4.2"),
    (0x19, "ldc.i4.3"),
    (0x1A, "ldc.i4.4"),
    (0x1B, "ldc.i4.5"),
    (0x1C, "ldc.i4.6"),
    (0x1D, "ldc.i4.7"),
    (0x1E, "ldc.i4.8"),
    (0x1F, "ldc.i4.s"),
    (0x20, "ldc.i4", 'i32'),
    (0x21, "ldc.i8", 'i64'),
    (0x22, "ldc.r4", 'f32'),
    (0x23, "ldc.r8", 'f64'),
    (0x25, "dup"),
    (0x26, "pop"),
    (0x27, "jmp", 'method'),
    (0x28, "call", 'method'),
    (0x29, "calli"),
    (0x2A, "ret"),
    (0x2B, "br.s", 'i8'),
    (0x2C, "brfalse.s", 'i8'),
    # Alias: (0x2C, "brnull.s", 'i8'),
    (0x2D, "brtrue.s", 'i8'),
    (0x2E, "beq.s", 'i8'),
    (0x2F, "bge.s", 'i8'),
    (0x30, "bgt.s", 'i8'),
    (0x31, "ble.s", 'i8'),
    (0x32, "blt.s", 'i8'),
    (0x33, "bne.un.s", 'i8'),
    (0x34, "bge.un.s", 'i8'),
    (0x35, "bgt.un.s", 'i8'),
    (0x36, "ble.un.s", 'i8'),
    (0x37, "blt.un.s", 'i8'),
    (0x38, "br", 'i32'),
    (0x39, "brfalse", 'i32'),
    (0x3A, "brtrue", 'i32'),
    (0x3B, "beq", 'i32'),
    (0x3C, "bge", 'i32'),
    (0x3D, "bgt", 'i32'),
    (0x3E, "ble", 'i32'),
    (0x3F, "blt", 'i32'),
    (0x40, "bne.un", 'i32'),
    (0x41, "bge.un", 'i32'),
    (0x42, "bgt.un", 'i32'),
    (0x43, "ble.un", 'i32'),
    (0x44, "blt.un", 'i32'),
    (0x45, "switch"),

    (0x58, "add"),
    (0x59, "sub"),
    (0x5A, "mul"),
    (0x5B, "div"),
    (0x5C, "div.un"),
    (0x5D, "rem"),
    (0x5E, "rem.un"),
    (0x5F, "and"),
    (0x60, "or"),
    (0x61, "xor"),
    (0x62, "shl"),
    (0x63, "shr"),
    (0x64, "shr.un"),
    (0x65, "neg"),
    (0x66, "not"),

    (0x67, "conv.i1"),
    (0x68, "conv.i2"),
    (0x69, "conv.i4"),
    (0x6A, "conv.i8"),
    (0x6B, "conv.r4"),
    (0x6C, "conv.r8"),
    (0x6D, "conv.u4"),
    (0x6E, "conv.u8"),

    (0x76, "conv.r.un"),

    (0x82, "conv.ovf.i1.un"),
    (0x83, "conv.ovf.i2.un"),
    (0x84, "conv.ovf.i4.un"),
    (0x85, "conv.ovf.i8.un"),
    (0x86, "conv.ovf.u1.un"),
    (0x87, "conv.ovf.u2.un"),
    (0x88, "conv.ovf.u4.un"),
    (0x89, "conv.ovf.u8.un"),
    (0x8A, "conv.ovf.i.un"),
    (0x8B, "conv.ovf.u.un"),

    (0xB3, "conv.ovf.i1"),
    (0xB4, "conv.ovf.u1"),
    (0xB5, "conv.ovf.i2"),
    (0xB6, "conv.ovf.u2"),
    (0xB7, "conv.ovf.i4"),
    (0xB8, "conv.ovf.u4"),
    (0xB9, "conv.ovf.i8"),
    (0xBA, "conv.ovf.u8"),

    (0xC3, "ckfinite"),

    (0xD1, "conv.u2"),
    (0xD2, "conv.u1"),
    (0xD3, "conv.i"),
    (0xD4, "conv.ovf.i"),
    (0xD5, "conv.ovf.u"),
    (0xD6, "add.ovf"),
    (0xD7, "add.ovf.un"),
    (0xD8, "mul.ovf"),
    (0xD9, "mul.ovf.un"),
    (0xDA, "sub.ovf"),
    (0xDB, "sub.ovf.un"),
    (0xDC, "endfault"),
    (0xDD, "leave", 'i32'),
    (0xDE, "leave.s", 'i8'),
    (0xDF, "stind.i"),
    (0xE0, "conv.u"),

]


class Instruction:
    def __init__(self, opcode):
        self.opcode = opcode

